Глава 4: Рефлексия
Обзор паттерна «Рефлексия»
В предыдущих главах мы рассмотрели базовые агентные паттерны: «Цепочки промптов» (Chaining) для последовательного выполнения, «Маршрутизацию» (Routing) для динамического выбора пути и «Параллелизацию» (Parallelization) для конкурентного исполнения. Эти паттерны позволяют агентам выполнять сложные задачи эффективнее и гибче. Однако даже при сложной оркестрации начальный вывод или план агента может быть не оптимален, неточен или неполон. Здесь на сцену выходит паттерн «Рефлексия» (Reflection).
Паттерн «Рефлексия» предполагает, что Agent оценивает собственную работу, выход или внутреннее состояние и использует эту оценку для повышения качества результата или уточнения ответа. Это форма самокоррекции и самоулучшения, позволяющая агенту итеративно полировать вывод или корректировать подход на основе обратной связи, внутренней критики или сравнения с заданными критериями. Иногда рефлексия может выполняться отдельным агентом, чья роль — анализировать вывод исходного агента.
В отличие от простой последовательной цепочки, где выход напрямую передаётся на следующий шаг, или маршрутизации, которая выбирает путь, рефлексия вводит контур обратной связи. Агент не просто выдаёт ответ; он затем рассматривает этот ответ (или процесс, породивший его), выявляет потенциальные проблемы и зоны улучшения и использует эти инсайты, чтобы создать улучшенную версию или подправить будущие действия.
Типичный процесс включает:
- Выполнение: агент выполняет задачу или генерирует первоначальный результат.
- Оценка/Критика: агент (часто через дополнительный вызов LLM или набор правил) анализирует результат предыдущего шага. Оценка может проверять фактическую корректность, связность, стиль, полноту, соответствие инструкциям и другие релевантные критерии.
- Рефлексия/Уточнение: на основе критики агент определяет, как улучшить результат. Это может означать генерацию новой, уточнённой версии, настройку параметров для следующего шага или даже модификацию общего плана.
- Итерация (необязательно, но типично): уточнённый результат или скорректированный подход затем исполняется, и процесс рефлексии может повторяться, пока не будет достигнуто удовлетворяющее качество или выполнено условие остановки.
Ключевая и очень эффективная реализация паттерна «Рефлексия» разделяет процесс на две логические роли: «Продюсер» и «Критик». Это часто называют моделью «Generator–Critic» или «Producer–Reviewer». Хотя один и тот же Agent может выполнять саморефлексию, использование двух специализированных агентов (или двух отдельных вызовов LLM с разными системными промптами) обычно даёт более устойчивые и менее предвзятые результаты.
Продюсер‑агент: его основная задача — выполнить первоначальное действие. Он полностью сосредоточен на генерации содержимого — будь то код, черновик статьи или план. Он принимает исходный промпт и выдаёт первую версию результата.
Критик‑агент: его единственная цель — оценить результат, сгенерированный Продюсером. Ему задают иной набор инструкций, часто отдельную «персону» (например, «Вы — ведущий инженер‑программист», «Вы — педантичный факт‑чекер»). Эти инструкции направляют Критика на анализ работы Продюсера по заданным критериям — фактическая корректность, качество кода, стиль, полнота. Его задача — найти недочёты, предложить улучшения и дать структурированную обратную связь.
Такое разделение ответственности ценно тем, что снижает «когнитивную предвзятость» самопроверки. Критик подходит к выводу со свежей позиции, уделяя внимание исключительно поиску ошибок и зон улучшения. Обратная связь от Критика передаётся обратно Продюсеру и служит руководством для генерации новой, улучшенной версии. Приведённые примеры кода на LangChain и ADK реализуют именно эту двухагентную модель: в примере LangChain используется специальный «reflector_prompt», создающий персону критика, а в примере ADK явно определены два агента — продюсер и рецензент.
Реализация рефлексии обычно требует включения контуров обратной связи в рабочий процесс агента. Это можно сделать через циклы в коде или при помощи фреймворков, поддерживающих управление состоянием и условные переходы на основе результатов оценки. Хотя единичный шаг «оценка → уточнение» может быть реализован в LangChain/LangGraph, ADK или Crew.AI, полноценная итеративная рефлексия чаще всего требует более сложной оркестрации.
Паттерн «Рефлексия» критически важен для построения агентов, способных выдавать высококачественные результаты, решать тонкие задачи и проявлять элементы самосознания и адаптивности. Он переводит систему от простого исполнения инструкций к более зрелому способу решения проблем и генерации контента.
Стоит отметить пересечение рефлексии с постановкой целей и мониторингом (см. глава 11). Цель задаёт конечный эталон для самооценки агента, а мониторинг отслеживает прогресс. Во многих практических случаях рефлексия выступает в роли корректирующего механизма, использующего мониторинговую обратную связь для анализа отклонений и корректировки стратегии. Эта синергия превращает агента из пассивного исполнителя в целевую систему, которая адаптивно работает на достижение своих задач.
Кроме того, эффективность паттерна «Рефлексия» значительно повышается, когда LLM ведёт память диалога (см. глава 8). История взаимодействий обеспечивает критический контекст для этапа оценки, позволяя агенту сопоставлять результат не изолированно, а на фоне предыдущих реплик, обратной связи и развивающихся целей. Это помогает учиться на прошлых замечаниях и не повторять ошибки. Без памяти каждая рефлексия — изолированное событие; с памятью рефлексия становится накопительным процессом, где каждый цикл опирается на предыдущий, приводя к более разумному и контекстно‑осведомлённому уточнению.
Практические применения и сценарии использования
Паттерн «Рефлексия» особенно полезен там, где критичны качество вывода, точность или соблюдение сложных ограничений:
Творческое письмо и генерация контента:
Уточнение сгенерированного текста, рассказов, стихов, маркетинговых материалов.- Сценарий: агент пишет блог‑пост.
- Рефлексия: создать черновик, оценить его на связность, тон и ясность, затем переписать с учётом критики. Повторять до достижения требуемого качества.
- Польза: более выверенный и эффективный контент.
- Сценарий: агент пишет блог‑пост.
Генерация и отладка кода:
Написание кода, поиск ошибок и их исправление.- Сценарий: агент пишет функцию на Python.
- Рефлексия: написать изначальную версию, запустить тесты или статический анализ, выявить ошибки/неэффективности, затем изменить код на основе находок.
- Польза: более надёжный и рабочий код.
- Сценарий: агент пишет функцию на Python.
Решение сложных задач:
Оценка промежуточных шагов или предложенных решений в многошаговых задачах рассуждения.- Сценарий: агент решает логическую головоломку.
- Рефлексия: предложить шаг, оценить, приближает ли он к решению или вводит противоречия; при необходимости откатиться и выбрать иной шаг.
- Польза: лучшая навигация по сложному пространству решений.
- Сценарий: агент решает логическую головоломку.
Суммаризация и синтез информации:
Уточнение суммаризаций на точность, полноту и краткость.- Сценарий: агент суммирует длинный документ.
- Рефлексия: сгенерировать первичную суммаризацию, сравнить с ключевыми пунктами исходника, дополнить недостающее и улучшить точность.
- Польза: более точные и полные суммаризации.
- Сценарий: агент суммирует длинный документ.
Планирование и стратегия:
Оценка предложенного плана и выявление потенциальных слабых мест.- Сценарий: агент планирует серию шагов для достижения цели.
- Рефлексия: сгенерировать план, смоделировать его исполнение или оценить реализуемость с учётом ограничений, доработать план по результатам.
- Польза: более эффективные и реалистичные планы.
- Сценарий: агент планирует серию шагов для достижения цели.
Разговорные агенты:
Ревизия предыдущих ходов диалога для удержания контекста, исправления недопониманий и повышения качества ответа.- Сценарий: чат‑бот поддержки клиентов.
- Рефлексия: после ответа пользователя пересмотреть историю диалога и последнее сгенерированное сообщение, чтобы обеспечить связность и корректно отреагировать на новый ввод.
- Польза: более естественные и эффективные разговоры.
- Сценарий: чат‑бот поддержки клиентов.
Рефлексия добавляет слой метакогниции в агентные системы, позволяя им учиться на собственных выводах и процессах и приводя к более разумным, надёжным и качественным результатам.
Практический пример кода (LangChain)
Реализация полноценной итеративной рефлексии требует механизмов управления состоянием и цикличного исполнения. Хотя в граф‑фреймворках вроде LangGraph это поддерживается нативно (или достигается в пользовательском коде), принцип одного цикла рефлексии удобно показать при помощи композиционного синтаксиса LCEL (LangChain Expression Language).
Этот пример реализует рефлексивный цикл на базе библиотеки LangChain и модели OpenAI GPT‑4o, итеративно генерируя и уточняя функцию на Python, вычисляющую факториал числа. Процесс стартует с постановки задачи, генерирует начальный код, а затем повторно рефлексирует на основе критики от симулированной роли «старшего инженера‑программиста», уточняя код на каждой итерации, пока стадия критики не решит, что код совершенен, или пока не будет достигнут максимум итераций. В конце скрипт печатает итоговый уточнённый код.
Сначала установите необходимые библиотеки:
pip install langchain langchain-community langchain-openaiТакже потребуется настроить окружение с API‑ключом выбранной модели (например, OpenAI, Google Gemini, Anthropic).
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
# --- Configuration ---
# Load environment variables from .env file (for OPENAI_API_KEY)
load_dotenv()
# Check if the API key is set
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY not found in .env file. Please add it.")
# Initialize the Chat LLM. We use gpt-4o for better reasoning.
# A lower temperature is used for more deterministic outputs.
llm = ChatOpenAI(model="gpt-4o", temperature=0.1)
def run_reflection_loop():
"""
Demonstrates a multi-step AI reflection loop to progressively improve a Python function.
"""
# --- The Core Task ---
task_prompt = """
Your task is to create a Python function named `calculate_factorial`.
This function should do the following:
1. Accept a single integer `n` as input.
2. Calculate its factorial (n!).
3. Include a clear docstring explaining what the function does.
4. Handle edge cases: The factorial of 0 is 1.
5. Handle invalid input: Raise a ValueError if the input is a negative number.
"""
# --- The Reflection Loop ---
max_iterations = 3
current_code = ""
# We will build a conversation history to provide context in each step.
message_history = [HumanMessage(content=task_prompt)]
for i in range(max_iterations):
print("\n" + "="*25 + f" REFLECTION LOOP: ITERATION {i + 1} " + "="*25)
# --- 1. GENERATE / REFINE STAGE ---
# In the first iteration, it generates. In subsequent iterations, it refines.
if i == 0:
print("\n>>> STAGE 1: GENERATING initial code...")
# The first message is just the task prompt.
response = llm.invoke(message_history)
current_code = response.content
else:
print("\n>>> STAGE 1: REFINING code based on previous critique...")
# The message history now contains the task,
# the last code, and the last critique.
# We instruct the model to apply the critiques.
message_history.append(HumanMessage(
content="Please refine the code using the critiques provided."
))
response = llm.invoke(message_history)
current_code = response.content
print("\n--- Generated Code (v" + str(i + 1) + ") ---\n" + current_code)
message_history.append(response) # Add the generated code to history
# --- 2. REFLECT STAGE ---
print("\n>>> STAGE 2: REFLECTING on the generated code...")
# Create a specific prompt for the reflector agent.
# This asks the model to act as a senior code reviewer.
reflector_prompt = [
SystemMessage(content="""
You are a senior software engineer and an expert
in Python.
Your role is to perform a meticulous code review.
Critically evaluate the provided Python code based
on the original task requirements.
Look for bugs, style issues, missing edge cases,
and areas for improvement.
If the code is perfect and meets all requirements,
respond with the single phrase 'CODE_IS_PERFECT'.
Otherwise, provide a bulleted list of your critiques.
"""),
HumanMessage(content=f"Original Task:\n{task_prompt}\n\nCode to Review:\n{current_code}")
]
critique_response = llm.invoke(reflector_prompt)
critique = critique_response.content
# --- 3. STOPPING CONDITION ---
if "CODE_IS_PERFECT" in critique:
print("\n--- Critique ---\nNo further critiques found. The code is satisfactory.")
break
print("\n--- Critique ---\n" + critique)
# Add the critique to the history for the next refinement loop.
message_history.append(HumanMessage(
content=f"Critique of the previous code:\n{critique}"
))
print("\n" + "="*30 + " FINAL RESULT " + "="*30)
print("\nFinal refined code after the reflection process:\n")
print(current_code)
if __name__ == "__main__":
run_reflection_loop()Код начинается с настройки окружения, загрузки API‑ключей и инициализации мощной языковой модели (например, GPT‑4o) с низкой температурой для более фокусированных выводов. Основная задача задаётся промптом — реализовать функцию Python для вычисления факториала, включая требования к docstring, обработке крайнего случая (факториал 0 равен 1) и обработке ошибочного ввода (исключение ValueError при отрицательном числе). Функция run_reflection_loop организует итеративный процесс: на первой итерации модель генерирует код по заданию, на следующих — уточняет его по замечаниям из предыдущего шага. Отдельная роль «рефлектора» (та же модель, но с иным системным промптом) выступает в роли старшего инженера, критикующего код по исходным требованиям. Если проблем нет, он отвечает «CODE_IS_PERFECT». Цикл продолжается до «совершенного» кода или достижения лимита итераций. История беседы сохраняется и передаётся модели на каждом шаге, обеспечивая контекст для генерации/уточнения и рефлексии. В финале скрипт печатает последнюю версию кода.
Практический пример кода (ADK)
Рассмотрим концептуальный пример на Google ADK. Он демонстрирует структуру Generator–Critic, где один компонент (Generator) производит первоначальный результат/план, а другой (Critic) даёт критическую обратную связь, направляя Generator к более точному и качественному финальному выводу.
from google.adk.agents import SequentialAgent, LlmAgent
# The first agent generates the initial draft.
generator = LlmAgent(
name="DraftWriter",
description="Generates initial draft content on a given subject.",
instruction="Write a short, informative paragraph about the user's subject.",
output_key="draft_text" # The output is saved to this state key.
)
# The second agent critiques the draft from the first agent.
reviewer = LlmAgent(
name="FactChecker",
description="Reviews a given text for factual accuracy and provides a structured critique.",
instruction="""
You are a meticulous fact-checker.
1. Read the text provided in the state key 'draft_text'.
2. Carefully verify the factual accuracy of all claims.
3. Your final output must be a dictionary containing two keys:
- "status": A string, either "ACCURATE" or "INACCURATE".
- "reasoning": A string providing a clear explanation for your status, citing specific issues if any are found.
""",
output_key="review_output" # The structured dictionary is saved here.
)
# The SequentialAgent ensures the generator runs before the reviewer.
review_pipeline = SequentialAgent(
name="WriteAndReview_Pipeline",
sub_agents=[generator, reviewer]
)
# Execution Flow:
# 1. generator runs -> saves its paragraph to state['draft_text'].
# 2. reviewer runs -> reads state['draft_text'] and saves its dictionary output to state['review_output'].Этот код демонстрирует последовательный конвейер агентов в Google ADK для генерации и рецензирования текста. Определены два LlmAgent: генератор и рецензент. Генератор создаёт исходный абзац по теме и сохраняет его в состояние по ключу draft_text. Рецензент выступает факт‑чекером: читает текст из draft_text, проверяет фактическую корректность, а на выход отдаёт словарь со статусом («ACCURATE»/«INACCURATE») и пояснением reasoning; результат сохраняется по ключу review_output. SequentialAgent под названием review_pipeline гарантирует, что сначала выполнится генератор, затем рецензент. Общий поток: генератор производит текст и сохраняет его; затем рецензент читает этот текст из состояния, проверяет и сохраняет структурированный вывод. Примечание: доступна и альтернативная реализация с использованием LoopAgent в ADK.
Перед завершением важно учесть, что хотя паттерн «Рефлексия» значительно повышает качество вывода, у него есть компромиссы. Итеративность, хоть и мощная, повышает стоимость и задержку, поскольку каждое уточнение требует нового вызова LLM, что делает паттерн не всегда подходящим для чувствительных к времени приложений. Кроме того, паттерн требователен к памяти; на каждой итерации растёт история общения — исходный вывод, критика, последующие улучшения.
Коротко
Что: Начальный вывод агента часто субоптимален — с неточностями, неполнотой или несоблюдением сложных требований. Базовые агентные рабочие процессы не содержат встроенного механизма, позволяющего агенту распознать и исправить собственные ошибки. Это решается за счёт того, что агент оценивает свою работу сам или, что надёжнее, с привлечением отдельного критика‑агента, благодаря чему исходный ответ не становится финальным независимо от его качества.
Почему: Паттерн «Рефлексия» вводит механизм самокоррекции и уточнения. Он организует контур обратной связи, где «продюсер» генерирует вывод, затем «критик» оценивает его по заданным критериям. Критика используется для генерации улучшенной версии. Итеративный цикл «генерация → оценка → уточнение» постепенно повышает качество результата, улучшая точность, связность и надёжность.
Практическое правило: Применяйте паттерн «Рефлексия», когда качество, точность и детализация финального результата важнее скорости и стоимости. Особенно эффективен для задач вроде подготовки выверенного длинного контента, написания и отладки кода, составления детальных планов. Используйте отдельного критика‑агента, когда требуются высокая объективность или специализированная оценка, которую может упустить универсальный продюсер‑агент.
Визуальное резюме
Рис. 1. Паттерн «Рефлексия», саморефлексия
Рис. 2. Паттерн «Рефлексия»: продюсер и агент‑критик
Ключевые выводы
- Главное преимущество: итеративная самокоррекция и уточнение выходов, приводящие к значительно более высокому качеству, точности и соответствию сложным инструкциям.
- Структура: контур «выполнение → оценка/критика → уточнение». Паттерн необходим там, где требуются высокое качество, точность и нюансированность.
- Сильная реализация: модель «Продюсер–Критик», где отдельный агент (или роль) оценивает исходный вывод. Разделение ролей повышает объективность и позволяет получить специализированную структурированную обратную связь.
- Компромиссы: рост задержек и вычислительных затрат; риск превысить контекстное окно модели или попасть под ограничение провайдера API.
- Реализация: полноценная итеративная рефлексия требует управления состоянием (например, LangGraph), но один цикл можно собрать в LangChain с LCEL, передав вывод на критику и последующее уточнение.
- ADK: поддерживает рефлексию через последовательные рабочие процессы, где вывод одного агента критикуется другим с последующим уточнением.
- Эффект: агент учится самокоррекции и повышает результаты со временем.
Заключение
Паттерн «Рефлексия» даёт важный механизм самокоррекции в рабочем процессе агента, обеспечивая итеративное улучшение вместо однопроходного исполнения. Это достигается контуром, в котором система генерирует результат, оценивает его по конкретным критериям и использует эту оценку для создания уточнённого вывода. Оценка может выполняться самим агентом (саморефлексия) или — что часто эффективнее — отдельным критиком‑агентом, что является ключевым архитектурным решением внутри паттерна.
Хотя полностью автономный многошаговый процесс рефлексии требует надёжной архитектуры управления состоянием, его ядро наглядно демонстрируется в одном цикле «генерация — критика — уточнение». Как управляющая структура, рефлексия хорошо сочетается с другими базовыми паттернами, помогая строить более устойчивые и функционально сложные агентные системы.
Ссылки
Ниже приведены ресурсы для дальнейшего чтения о паттерне «Рефлексия» и смежных концепциях:
- Training Language Models to Self-Correct via Reinforcement Learning
- Документация LangChain Expression Language (LCEL)
- Документация LangGraph
- Документация Google Agent Developer Kit (ADK) (Multi‑Agent Systems)
Навигация
Назад: Глава 3. Параллелизация
Вперед: Глава 5. Использование инструментов